/*!

@author
*/
#include <stdafx.h>

#include "Input.h"


InputManager* InputManager::m_pInstance	= NULL;

InputManager::InputManager()
{
	ZeroMemory(&m_key, sizeof(m_key));
	ZeroMemory(&m_lastKey, sizeof(m_lastKey));

	m_mouseButtons = 0;
	m_mouseLastX = 0;
	m_mouseLastY = 0;
	m_mouseX = 0;
	m_mouseY = 0;
}

InputManager::~InputManager()
{
}


bool InputManager::WinEventHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(hWnd);
	UNREFERENCED_PARAMETER(lParam);

	switch(msg)
	{
		// Keyboard ---------------------------------------------------------------
	case WM_CHAR:
		{
			InputEvent event(INPUT_EVENT_TEXT);
			event.textEvent.character = wParam;
			Send(event);
		}
		break;
	case WM_KEYDOWN:
	case WM_SYSKEYDOWN: 
		if (wParam < 256)
		{
			m_key[wParam] = true;
			InputEvent event(INPUT_EVENT_KEY);
			event.keyEvent.pressed = true;
			event.keyEvent.scancode = wParam;
			Send(event);
		}
		if (msg == WM_SYSKEYDOWN)
			return false; // Do not forward syskeydown
		break;
	case WM_KEYUP:
	case WM_SYSKEYUP:
		if (wParam < 256)
		{
			m_key[wParam] = false;
			InputEvent event(INPUT_EVENT_KEY);
			event.keyEvent.pressed = false;
			event.keyEvent.scancode = wParam;
			Send(event);
		}
		if (msg == WM_SYSKEYDOWN)
			return false; // Do not forward syskeydown (alt)
		break;
		// Mouse ------------------------------------------------------------------
	case WM_MOUSEMOVE:
		m_mouseX = int16(LOWORD(lParam)); 
		m_mouseY = int16(HIWORD(lParam));

		break;
	case WM_MOUSEWHEEL:
		{
			int wheel = GET_WHEEL_DELTA_WPARAM(wParam);
			if (wheel > 0)
				m_mouseButtons |= Mouse::BTN_WHEEL_UP;
			else if (wheel < 0)
				m_mouseButtons |= Mouse::BTN_WHEEL_DN;

			InputEvent event(INPUT_EVENT_MOUSE);
			event.mouseEvent.buttons = m_mouseButtons;
			Send(event);
		}
		break;
	case WM_LBUTTONDOWN:
		m_mouseButtons |= Mouse::BTN_LEFT;
		break;
	case WM_LBUTTONUP:
		m_mouseButtons &= ~Mouse::BTN_LEFT;
		break;
	case WM_LBUTTONDBLCLK:
		m_mouseButtonDC |= Mouse::BTN_LEFT;
		break;
	case WM_RBUTTONDOWN:
		m_mouseButtons |= Mouse::BTN_RIGHT;
		break;
	case WM_RBUTTONUP:
		m_mouseButtons &= ~Mouse::BTN_RIGHT;
		break;
	case WM_RBUTTONDBLCLK:
		m_mouseButtonDC |= Mouse::BTN_RIGHT;
		break;
	case WM_MBUTTONDOWN:
		m_mouseButtons |= Mouse::BTN_CENTER;
		break;
	case WM_MBUTTONUP:
		m_mouseButtons &= ~Mouse::BTN_CENTER;
		break;
	case WM_MBUTTONDBLCLK:
		m_mouseButtonDC |= Mouse::BTN_CENTER;
		break;
	case WM_KILLFOCUS:
		m_mouseButtons = 0;
		ZeroMemory(&m_key, sizeof(m_key));
		ZeroMemory(&m_lastKey, sizeof(m_lastKey));
		break;
	}
	return true;
}


void InputManager::RegisterInputHandler(InputEventHandler* handler)
{
	// Check for duplicate handlers
	for(size_t i=0;i<m_inputHandlers.size();i++)
	{
		assert(m_inputHandlers[i] != handler);
		if (m_inputHandlers[i] == handler)
			return;
	}

	m_inputHandlers.push_back(handler);
}

void InputManager::Update()
{
	m_mouseLastX = m_mouseX;
	m_mouseLastY = m_mouseY;
	m_lastMouseButtons = m_mouseButtons;

	m_mouseButtons &= ~Mouse::BTN_WHEEL_UP;
	m_mouseButtons &= ~Mouse::BTN_WHEEL_DN;
	m_mouseButtonDC = 0;

	memcpy(m_lastKey,m_key,sizeof(m_key));
}
